package jdbc.study.mapper;

import com.sun.org.apache.xml.internal.res.XMLErrorResources_tr;
import jdbc.study.annotation.Logic;
import jdbc.study.annotation.Table;
import jdbc.study.domain.JDBCInfo;
import jdbc.study.domain.Movie;
import jdbc.study.domain.Page;
import jdbc.study.utils.DataSourceUtils;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.*;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class Cell<T> {

    /**
     * 获取泛型的具体类型的方法
     * @return 泛型的具体类型
     */
    public Class getCellType() {
        //获取到当前类的父类的符号类型
        Type superClassType = this.getClass().getGenericSuperclass();
        //如果父类是泛型
        if(superClassType instanceof ParameterizedType) {
            //类型强转，把Class转换成ParameterizedType
            ParameterizedType parameterizedType = (ParameterizedType) superClassType;
            //获取到泛型类型的值
            Type[] actualType = parameterizedType.getActualTypeArguments();
            if(actualType.length>0) {
                return (Class) actualType[0];
            }else {
                return null;
            }
        }else {
            return null;
        }
    }

    public List<T> selectList(Page page, JDBCInfo jdbcInfo) throws SQLException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IntrospectionException {
        List<T> result = new ArrayList<>();
        Class targetClass = getCellType();
        DataSourceUtils dataSourceUtils = new DataSourceUtils();
        dataSourceUtils.initSimpleConnection(jdbcInfo.getUrl(), jdbcInfo.getUser(), jdbcInfo.getPassword());
        String sql = "select * from "+getAnnotationTableName(targetClass)+" where "+getAnnotationLogicDeleted(targetClass)+" = 0 limit ?, ?";
        int index = (page.getNo()-1)*page.getSize();
        ResultSet resultSet = dataSourceUtils.doSQL(sql, index, page.getSize());
        ResultSetMetaData metaData = resultSet.getMetaData();
        int columnCount = metaData.getColumnCount();
        while(resultSet.next()) {
            T item = (T) targetClass.getConstructor(null).newInstance();
            for(int i = 1; i <= columnCount; i++) {
                String columnLabel = metaData.getColumnLabel(i);
                Object columnValue = resultSet.getObject(columnLabel);

                PropertyDescriptor propertyDescriptor = new PropertyDescriptor(columnLabel, targetClass);
                Method method = propertyDescriptor.getWriteMethod();
                method.invoke(item, columnValue);
            }
            result.add(item);
        }

        return result;
    }

    public String getTableName(Class targetClass) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IntrospectionException {
        T only = (T) targetClass.getConstructor(null).newInstance();
        PropertyDescriptor propertyDescriptor = new PropertyDescriptor("tableName", targetClass);
        Method method = propertyDescriptor.getReadMethod();
        String tableName = (String) method.invoke(only);
        return tableName;
    }

    public String getAnnotationTableName(Class targetClass) {
        Table table = (Table) targetClass.getAnnotation(Table.class);
        String tableName = table.name();
        return tableName;
    }

    public String getAnnotationLogicDeleted(Class targetClass) {
        Field[] fields = targetClass.getDeclaredFields();
        for(int i = 0; i < fields.length; i++) {
            if(fields[i].isAnnotationPresent(Logic.class)) {
                return fields[i].getName();
            }
        }
        return "deleted";
    }
}
